package org.totoro.concurrent.juc.cas;

import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author yhl
 * @Description:
 * @date：2017/10/11 0011
 * @tiem：14:34
 */
public class TestCAS {

    private volatile int value;

    private static final long VALUE_OFFSET;

    private static Unsafe unsafe;

    static {

        try {
            // 通过反射获取rt.jar下的Unsafe类
            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafeInstance.setAccessible(true);
            // return (Unsafe) theUnsafeInstance.get(null);是等价的
            unsafe = (Unsafe) theUnsafeInstance.get(Unsafe.class);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }


        /**
         * 获取偏移量
         */

        try {
            VALUE_OFFSET = unsafe.objectFieldOffset
                    (TestCAS.class.getDeclaredField("value"));
        } catch (Exception ex) {
            throw new Error(ex);
        }

    }

    public int getValue() {
        return value;
    }

    /**
     * 常见的方法列表
     * <p>
     * 尝试新增后对比，若增加成功则返回true否则返回false
     *
     * @see Unsafe#compareAndSwapLong(Object, long, long, long)
     * @see Unsafe#compareAndSwapInt(Object, long, int, int)
     * @see Unsafe#compareAndSwapObject(Object, long, Object, Object)
     * <p>
     * <p>
     * 如果修改成功，就返回修改前的值
     * @see Unsafe#getAndSetInt(Object, long, int)
     * @see Unsafe#getAndSetLong(Object, long, long)
     * @see Unsafe#getAndSetObject(Object, long, Object)
     * <p>
     * <p>
     * 获取当前内存中的值
     * @see Unsafe#getIntVolatile(Object, long)
     */

    public void addCompareAndSwapInt(int num) {


        //第一种
        //   unsafe.getAndAddInt(this, VALUE_OFFSET, num);


        // 第二种
        for (; ; ) {

            //  获取当前内存中的值
            int intVolatile = unsafe.getIntVolatile(this, VALUE_OFFSET);

            int newValue = intVolatile + num;

            boolean b = unsafe.compareAndSwapInt(this, VALUE_OFFSET, intVolatile, newValue);

            if (b == true) {
                break;
            }

        }


    }


    public static void main(String[] args) throws Exception {


        TestCAS testCAS = new TestCAS();

        int jobNum = 100000;

        AtomicInteger atomicInteger = new AtomicInteger(0);

        ExecutorService executorService = Executors.newFixedThreadPool(100);

        List<Future<?>> jobList = new ArrayList<>();

        for (int i = 0; i < jobNum; i++) {
            Future<?> submit = executorService.submit(new Runnable() {
                @Override
                public void run() {
                    testCAS.addCompareAndSwapInt(1);
                    atomicInteger.getAndAdd(1);
                }
            });

            jobList.add(submit);

        }

        for (int i = 0; i < jobList.size(); i++) {


            /**
             *

             在启动JVM的时候，只需增加-Xint或者-Djava.compiler=NONE选项即可：

             java -Xint your_main_class_file_name

             java -Djava.compiler your_main_class_file_name

             也可以通过参数去设置 达到多少次，才触发即时编译

             *
             */

            // 可能存在  jit（即时编译）  情况
            jobList.get(i);


        }

        System.out.println(" testCAS    " + testCAS.getValue());

        System.out.println(" atomicInteger " + atomicInteger.get());

        executorService.shutdown();

    }
}
